package com.codemonkey.lq.extend.excelverification.impl;

import java.util.HashMap;

import org.apache.ibatis.scripting.xmltags.ExpressionEvaluator;

import com.codemonkey.lq.extend.excelverification.AbstractVerifier;
import com.codemonkey.lq.extend.excelverification.CellContext;

public class ExpressionVerifier extends AbstractVerifier {

	/**
	 * 在进行表达式评估时, 当前单元格的值在表达式中的key标识
	 */
	@SuppressWarnings("unused")
	public static final String VALUE_TAG = "$value";
	private static final ExpressionEvaluator DEFAULT = new ExpressionEvaluator();

	private final String expression;
	private final String failMsg;

	public ExpressionVerifier(String expression, String failMsg) {
		this.expression = expression;
		this.failMsg = failMsg;
	}

	@Override
	protected boolean doVerify(final CellContext cellContext) {
		boolean isPass = DEFAULT.evaluateBoolean(expression, new HashMap<String, Object>() {
			/**
			 * 
			 */
			private static final long serialVersionUID = 0L;

			@Override
			public Object get(Object key) {
				if (null == key) {
					return "";
				}

				if (key.toString().equalsIgnoreCase(ExpressionVerifier.VALUE_TAG)) {
					return cellContext.getCellVal();
				}

				return cellContext.getRowContext().get(key);
			}
		});
		if (isPass) {
			// NO OP
		} else {
			StringBuilder sb = new StringBuilder("###");
			sb.append(this.getClass().getSimpleName()).append("[ ");
			sb.append(expression).append(" ] ").append(System.lineSeparator());
			
			commonConstructFailContextInfo(cellContext, sb);
			
			sb.append(" failMsg: [ ").append(failMsg).append(" ] ").append(System.lineSeparator());
			cellContext.addErrorMsg(sb.toString());
		}

		return isPass;
	}

	@Override
	public String toString() {
		StringBuilder sb = new StringBuilder("###");
		sb.append(this.getClass().getSimpleName()).append(" : \r\n");
		sb.append("expression : [ ").append(this.expression).append(" ] \r\n");
		sb.append("failMsg : [ ").append(this.failMsg).append(" ] \r\n");
		return sb.toString();
	}

	@Override
	public String getReadableFailMsg(CellContext cellContext) {
		return failMsg;
	}
}
